package cc.telecomdigital.tdstock.Http.Services;

import java.io.IOException;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import android.content.Context;
import android.os.ConditionVariable;
import cc.telecomdigital.tdstock.ITDLApplication;
import cc.telecomdigital.tdstock.Framework.UniqueItem.DeviceInfo;
import cc.telecomdigital.tdstock.Framework.UniqueItem.TDStockLog;
import cc.telecomdigital.tdstock.Http.H_CODE;
import cc.telecomdigital.tdstock.Services.LS_UserClient.ILS_UserClient_Authentication_Report;
import cc.telecomdigital.tdstock.Services.LS_UserClient.LS_UserClient_Authentication_Result;
import cc.telecomdigital.tdstock.utils.Futures;
import cc.telecomdigital.tdstock.utils.Fx;
import cc.telecomdigital.tdstock.utils.Index;
import cc.telecomdigital.tdstock.utils.Metal;
import cc.telecomdigital.tdstock.utils.Oil;
import cc.telecomdigital.tdstock.utils.Stock;
import cc.telecomdigital.tdstock.utils.WorldFutures;
import cc.telecomdigital.tdstock.utils.WorldIndex;

/**
 * Send http request service obj
 * @author ouyangzhihui
 *
 */
public class H_HttpServiceRequest extends H_SendTemplate
{
	static final private String LOG_TAG = "HttpServiceRequest"; 
	
	public interface IH_UserClient_HttpRequest_Report
	{
		void H_UserClient_HttpRequest_Response(H_UserClient_HttpRequest_Result iResult);
	}

	public class H_UserClient_HttpRequest_Result extends H_GatewayResult
	{
		public String 			seqID;
		
		public Object[] 		objArrayStores;
		public Map<String, ?>	objMapStores;
		public List<?>			objListStores;
		public List<String[]>	contentStores;
		
		public List<String[]>	attrStores;

		public H_UserClient_HttpRequest_Result()
		{
			super();
			objArrayStores = new Object[]{ };
			objListStores = new ArrayList<Object>();
			objMapStores = new HashMap<String, Object>();
			contentStores = new ArrayList<String[]>();
			attrStores = new ArrayList<String[]>();
			seqID = "";
		}

		public void SetDataResult(List<String[]> iNewList)
		{
			contentStores.clear();
			contentStores.addAll(iNewList);
		}
		
		public void SetAttrDataResult(List<String[]> iNewList)
		{
			attrStores.clear();
			attrStores.addAll(iNewList);
		}
		
		public void SetDataResultMapObj(Map<String, ?> iNewList)
		{
			objMapStores.clear();
			objMapStores = iNewList;
		}
		
		public void SetDataResultListObj(List<?> iNewList)
		{
			objListStores.clear();
			objListStores = iNewList;
		}
		
		public void SetDataResultObjBmpArray(Object[] iNewList)
		{
			objArrayStores = null;
			objArrayStores = iNewList;
		}

		public void SetHRequestSeqID(String iSeqID)
		{
			if (iSeqID != null)
				iSeqID = iSeqID.trim();
			seqID = iSeqID;
		}
	}

	private IH_UserClient_HttpRequest_Report	handler;
	private String seqID;

	public H_HttpServiceRequest(Context iCaller, final String iSeqID)
	{
		super(iCaller);
		handler = null;
		rootName = null;
		fieldNames = null;
		entityRootName = null;
		headerFieldNames = null;
		seqID = iSeqID;
	}
	
	private ConditionVariable retryLogonConnection;

	public H_CODE SubmitRequest(final String urlString, IH_UserClient_HttpRequest_Report iHandler)
	{
		H_CODE status;
		status = H_CODE.OK;
		
//		if(!DeviceInfo.IsNetworkAvailable(callerContext))
//			return H_CODE.NO_NETWORK;
		
		handler = iHandler;
		
		retryLogonConnection = new ConditionVariable();
		
		Thread internalThreadObj = new Thread()
		{
			@Override
			public void run()
			{
				HttpGet targetGet;
				HttpClient targetClient;
				H_UserClient_HttpRequest_Result requestResult;

				targetGet = GetHttpGet(urlString);
				targetClient = GetDefaultHttpClient();
				
				if ((!DeviceInfo.IsNetworkAvailable(callerContext)) || (targetGet == null) || (targetClient == null))
				{
					String resultCode;
					String resultString;
					// Our custom define error, in the Send Parent Template, positive allow a retry
					resultCode = "1";
					resultString = GetInnerErrorMessage(resultCode);
					requestResult = new H_UserClient_HttpRequest_Result();
					requestResult.SetHRequestSeqID(seqID);
					requestResult.SetGateWayStatus(resultCode, resultString);
					
					if (debugMode)
						TDStockLog.i(LOG_TAG, "Error: " + resultCode + ", " + resultString);

					if (handler != null)
						handler.H_UserClient_HttpRequest_Response(requestResult);

					return;
				}

				int trialCount = 0, siTrialCount = 0;
				
				while (true)
				{
					TDStockLog.d(LOG_TAG, "SendDataSub...");
					
					requestResult = SendDataSub(targetClient, targetGet);
					
					TDStockLog.d(LOG_TAG, "SendDataSub...ok");
					
					// Session expired
					if (requestResult.MStatus.equals("-1") || "".equals(accountNum) || "".equals(sessionKey))
					{
						++siTrialCount;
						if (siTrialCount < sessionTrialMax)
						{
							// Retry Get SessionKey
							TDStockLog.d(LOG_TAG, "Session expired, retry..."+siTrialCount);
							
							try
							{
								H_CODE statusCode;
								statusCode = HttpAppInfo.SendFrameworkReLogonRequest(new ILS_UserClient_Authentication_Report()
								{
									@Override
									public void LS_UserClient_Authentication_Response(LS_UserClient_Authentication_Result iResponse)
									{
										retryLogonConnection.open();
										
										if (iResponse == null)
										{
											return;
										}
						
										if (iResponse.successfulSend == false)
										{
											return;
										}
						
										String errorMsg = iResponse.errorMessage;
										
										if (debugMode)
											TDStockLog.i(LOG_TAG, "Framework Logon=>ErrorMessage: " + errorMsg);
										
										if (iResponse.statusCode.equals("0"))
										{
											String accountNumber = ((ITDLApplication)callerContext.getApplicationContext()).GetLSClient_AccountLogonName();
											String sessionKey = ((ITDLApplication)callerContext.getApplicationContext()).GetLSClient_SessionKey();
											
											SetAccountInformation(accountNumber, sessionKey);
											
											TDStockLog.d(LOG_TAG, "Framework Logon=>Sessionkey: "+accountNumber+","+sessionKey);
										}
									}
								});
								
								if(statusCode == H_CODE.OK)
								{
									TDStockLog.i(LOG_TAG, "SendFrameworkLogonRequest success...");
									
									retryLogonConnection.block(CONNECT_TIMEOUT * 2);
									
									TDStockLog.d(LOG_TAG, "SendFrameworkLogonRequest callback wait complete...");
									
									targetGet = GetHttpGet(urlString);
									targetClient = GetDefaultHttpClient();
								}
								else
								{
									if (debugMode)
										TDStockLog.i(LOG_TAG, "SendFrameworkLogonRequest fail...");
									continue;
								}
							}
							catch (Exception ex)
							{
								TDStockLog.e(GetIdentity(), "SubmitRequest=>Exception=" + ex.toString());
								ex.printStackTrace();
							}
							continue;
						}
					}
					
					// If we did not get the require recall information, might or might not retry
					if (requestResult.MStatus.length() == 0 || !requestResult.MStatus.equals("0"))
					{
						// Retry 
						if (debugMode)
							TDStockLog.i(LOG_TAG, "SubmitRequest=>Exception=" + requestResult.MError+","+requestResult.MStatus);
						++trialCount;
						if (trialCount < trialMax)
						{
							if (debugMode)
								TDStockLog.i(LOG_TAG, "SubmitRequest: Retry performed: " + trialCount);
							try
							{
								sleep(RETRY_DELAY_TIME);
							}
							catch (Exception ex)
							{
								TDStockLog.e(GetIdentity(), "SubmitRequest=>Exception=" + ex.toString());
								ex.printStackTrace();
							}
							continue;
						}
					}
					
					break;
				}

				// We have try but we have no reply
				if (requestResult.MStatus.length() == 0)
				{
					String resultCode;
					String resultString;
					//
					resultCode = "-2";
					resultString = GetInnerErrorMessage(resultCode);
					requestResult = new H_UserClient_HttpRequest_Result();
					requestResult.SetHRequestSeqID(seqID);
					requestResult.SetGateWayStatus(resultCode, resultString);
				}

				if (debugMode)
					TDStockLog.i(LOG_TAG, "Error: " + requestResult.MStatus + ", " + requestResult.MError);

				if (handler != null)
					handler.H_UserClient_HttpRequest_Response(requestResult);
			}
		};

		internalThreadObj.start();

		return status;
	}
	
	private H_UserClient_HttpRequest_Result SendDataSub(HttpClient iClient, HttpGet iGetURL) 
	{
		H_UserClient_HttpRequest_Result reqResult;
		String                 MErrorStatus, MErrorMessage;
		HttpResponse		   response;
		Document               docFile;

		reqResult     = new H_UserClient_HttpRequest_Result();
		reqResult.SetHRequestSeqID(seqID);
		try
		{
			StatusLine httpStatus;

//			synchronized(httpLock)
//			{
				response = iClient.execute(iGetURL);
//			}
			
			httpStatus = response.getStatusLine();
			
			TDStockLog.d(LOG_TAG, "HttpStatus: "+httpStatus.getStatusCode()+","+httpStatus.getReasonPhrase());
			
			//Close the connection if not reachable or others, usually not happen
			if (httpStatus.getStatusCode() != HttpStatus.SC_OK)
			{
				response.getEntity().getContent().close();
				return reqResult;
			}

//			if(debugMode)
//				TDStockLog.d(LOG_TAG, "Get Xml Dcoument file...start");
			docFile = GetXmlFormatData(response.getEntity().getContent());
//			if(debugMode)
//				TDStockLog.d(LOG_TAG, "Get Xml Dcoument file...end");
			if(docFile == null)
				return reqResult;

			//The document is within the TAG of Root flag
			NodeList rootList;
			Element  focusElement;
			
			//The document is within the TAG of Authentication session is expired
			rootList = docFile.getElementsByTagName("Authentication"); //session.
			//Well we know we only have one
			if (rootList.getLength() == 1)
			{
				//change our focus of the root list
				focusElement  = (Element)rootList.item(0);
				reqResult     = (H_UserClient_HttpRequest_Result)H_SessionInfoParser(focusElement, reqResult); //Session:Status,ErrorMessage
				return reqResult;
			}
			
			//The document is within the TAG of Root flag
			rootList = docFile.getElementsByTagName(rootName);
			
//			if(debugMode)
//				TDStockLog.d(LOG_TAG, "rooList length: "+rootList.getLength());
			
			//Well we know we only have one
			if (rootList.getLength() < 1)
			{
				MErrorStatus  = "-7";
				MErrorMessage = GetInnerErrorMessage(MErrorStatus);
				reqResult.SetGateWayStatus(MErrorStatus, MErrorMessage);
				
				return reqResult;
			}
			
			//change our focus of the root list
			focusElement  = (Element)rootList.item(0);
			reqResult     = (H_UserClient_HttpRequest_Result)H_GatewayInfoParser(focusElement, reqResult); //Status,ErrorMessage

			reqResult = H_HttpXMLInfoParser(docFile, reqResult);
		}
		catch(SocketTimeoutException e)
		{
			e.printStackTrace();
			TDStockLog.e(GetIdentity(), "SendDataSub=>SocketTimeoutException: " + e.toString());
			
			MErrorStatus  = "-12";
			MErrorMessage = GetInnerErrorMessage(MErrorStatus);
			reqResult.SetGateWayStatus(MErrorStatus, MErrorMessage);
		}
		catch (ClientProtocolException e)
		{
			e.printStackTrace();
			TDStockLog.e(GetIdentity(), "SendDataSub=>ClientProtocolException: " + e.toString());
			
			MErrorStatus  = "-2";
			MErrorMessage = GetInnerErrorMessage(MErrorStatus);
			reqResult.SetGateWayStatus(MErrorStatus, MErrorMessage);
		}
		catch (IOException e)
		{
			e.printStackTrace();
			TDStockLog.e(GetIdentity(), "SendDataSub=>IOException: " + e.toString());
			
			MErrorStatus  = "-2";
			if(e.toString().contains("SocketTimeout"))
				MErrorStatus = "-12";
			MErrorMessage = GetInnerErrorMessage(MErrorStatus);
			reqResult.SetGateWayStatus(MErrorStatus, MErrorMessage);
		}
		catch (Exception e)
		{
			e.printStackTrace();
			TDStockLog.e(GetIdentity(), "SendDataSub=>Exception: " + e.toString());
			
			MErrorStatus  = "-2";
			MErrorMessage = GetInnerErrorMessage(MErrorStatus);
			reqResult.SetGateWayStatus(MErrorStatus, MErrorMessage);
		}
		
		return reqResult;
	}
	
	/** Parse the info after the XML Info **/
	private H_UserClient_HttpRequest_Result H_HttpXMLInfoParser(Document iDoc, H_UserClient_HttpRequest_Result iResult)
	{
		/**BMP stock page*/
		if(rootName == "BMP" && entityRootName != null && fieldNames == null && headerFieldNames == null)
		{
			Object[] iNewList;
			
			if(entityRootName.split(",").length <= 3)
				iNewList = BMPStockPageAllInfoDecode(iDoc);
			else
				iNewList = BMPMonitorInfoDecode(iDoc);
			
			iResult.SetDataResultObjBmpArray(iNewList);
			return iResult;
		}
		
		/**Not Bmp stock page, other...*/
		List<String[]> contentList;
		contentList = new ArrayList<String[]>();
		
		try
		{
			if(headerFieldNames != null && headerFieldNames.length >= 1)
			{
				String tmpString;
				String[] iHArray = new String[headerFieldNames.length];
				for(int i = 0; i < headerFieldNames.length; i++)
				{
					try
					{
						Node node = iDoc.getElementsByTagName(headerFieldNames[i]).item(0);
						if(node == null)
							tmpString = "";
						else
							tmpString = node.getFirstChild().getNodeValue();
						tmpString = tmpString == null ? "" : tmpString;
					}
					catch(Exception e)
					{
						e.printStackTrace();
						tmpString = "";
					}
					iHArray[i] = tmpString;
					
					if(debugMode)
						TDStockLog.d(LOG_TAG, "XML-HeaderFieldValue=> " + iHArray[i]);
				}
				contentList.add(iHArray);
			}
		}
		catch(Exception ex)
		{
			TDStockLog.e(LOG_TAG, "H_RecallInfoParser>Header=>Exception: " + ex.toString());
			ex.printStackTrace();
		}
		
		try
		{
			List<String[]> attrList;
			attrList = new ArrayList<String[]>();
			
			if(fieldValueList)
				TransactionByFieldListInfoDecode(iDoc, contentList, attrList);
			else
				TransactionInfoDecode(iDoc, contentList, attrList);

			iResult.SetDataResult(contentList);
			iResult.SetAttrDataResult(attrList);
		}
		catch(Exception ex)
		{
			TDStockLog.e(LOG_TAG, "H_RecallInfoParser>TransactionInfoDecode=>Exception: " + ex.toString());
			ex.printStackTrace();
		}
		if (debugMode)
			TDStockLog.i(LOG_TAG, "XMLInfo=>Error="+iResult.MStatus+","+iResult.MError);
		return iResult;
	}
	
	private Object[] BMPStockPageAllInfoDecode(Document iDocument)
	{
		Map<String, Futures> futuresList = new HashMap<String, Futures>();
		Map<String, Index> indexList = new HashMap<String, Index>();
		WorldIndex worldIndex = new WorldIndex();
		Stock stock = null;
		String serverTime = "";
		
		try
		{
			// Stock,Index
			NodeList indexNodes = iDocument.getElementsByTagName("STOCKLIST");
			NodeList indexNode = indexNodes.item(0).getChildNodes();
			for (int i = 1; i < indexNode.getLength(); i++)
			{
				Element bElement = (Element) indexNode.item(i);
				NodeList childNodes = bElement.getChildNodes();
				
				// Index
				if(bElement.getAttributes().getLength() > 0/* && "INDEX".equals(bElement.getAttributes().item(0).getFirstChild().getNodeValue())*/)
				{
//					Node attrNode = bElement.getAttributes().item(0);
//					System.out.println(attrNode.getNodeName()+" , "+attrNode.getFirstChild().getNodeValue());
					// Object
					Index index = new Index();
					for (int j = 0; j < childNodes.getLength(); j++)
					{
						if (childNodes.item(j).getNodeType() == Node.ELEMENT_NODE)
						{
							String name = childNodes.item(j).getNodeName();
							for(int k = 0; k < Index.FIELD_ITEMS_STOCK.length; k++)
							{
								try
								{
									if (Index.FIELD_ITEMS_STOCK[k].equals(name))
									{
										index.SetValueByFIELDS_STOCK(k, childNodes.item(j).getFirstChild().getNodeValue());
										break;
									}
								}
								catch(Exception e)
								{
								}
							}
						}
					}
					indexList.put(index.getName(), index);
				}
				else  // Stock
				{
					stock = new Stock();
					for (int j = 0; j < childNodes.getLength(); j++)
					{
						if (childNodes.item(j).getNodeType() == Node.ELEMENT_NODE)
						{
							String name = childNodes.item(j).getNodeName();
							for(int k = 0; k < Stock.FIELD_ITEMS_All.length; k++)
							{
								try
								{
									if (Stock.FIELD_ITEMS_All[k].equals(name))
									{
										stock.SetValueByFIELDS(k, childNodes.item(j).getFirstChild().getNodeValue());
										break;
									}
								}
								catch(Exception e)
								{
								}
							}
						}
					}
				}
			}
			
			// Futures
			NodeList futureNodes = iDocument.getElementsByTagName("Future");
			NodeList futureIndexNode = futureNodes.item(0).getChildNodes();
			for (int i = 0; i < futureIndexNode.getLength(); i++)
			{
				Element bElement = (Element) futureIndexNode.item(i);
				NodeList childNodes = bElement.getChildNodes();
				// Object
				Futures futures = new Futures();
				for (int j = 0; j < childNodes.getLength(); j++)
				{
					if (childNodes.item(j).getNodeType() == Node.ELEMENT_NODE)
					{
						String name = childNodes.item(j).getNodeName();
						for(int k = 0; k < Futures.FIELD_ITEMS_STOCK.length; k++)
						{
							if (Futures.FIELD_ITEMS_STOCK[k].equals(name))
							{
								futures.SetValueByFIELDS_STOCK(k, childNodes.item(j).getFirstChild().getNodeValue());
								break;
							}
						}
					}
				}
				futuresList.put(futures.getName(), futures);
			}
			
			// WorldIndex SSEI
			NodeList worldIndexNodes = iDocument.getElementsByTagName("Index");
			NodeList worldIndexNode = worldIndexNodes.item(0).getChildNodes();
			Element bElement = (Element) worldIndexNode.item(0);
			NodeList childNodes = bElement.getChildNodes();
			// Object
			for (int j = 0; j < childNodes.getLength(); j++)
			{
				if (childNodes.item(j).getNodeType() == Node.ELEMENT_NODE)
				{
					String name = childNodes.item(j).getNodeName();
					for(int k = 0; k < WorldIndex.FIELD_ITEMS_MONITOR.length; k++)
					{
						if (WorldIndex.FIELD_ITEMS_MONITOR[k].equals(name))
						{
							worldIndex.SetValueByFIELDS_MONITOR(k, childNodes.item(j).getFirstChild().getNodeValue());
							break;
						}
					}
				}
			}
			
			// Server Time
			NodeList timeNodes = iDocument.getElementsByTagName("Time");
			if(timeNodes.item(0).getNodeType() == Node.ELEMENT_NODE)
			{
				try
				{
					serverTime = timeNodes.item(0).getFirstChild().getNodeValue();
				}
				catch(Exception e)
				{
				}
			}
		}
		catch (Exception e)
		{
		}
		return new Object[] { indexList, futuresList, worldIndex, stock, serverTime };
	}
	
	private Object[] BMPMonitorInfoDecode(Document iDocument)
	{
		Map<String, Stock> stockList = new HashMap<String, Stock>();
		Map<String, Index> indexList = new HashMap<String, Index>();
		Map<String, WorldIndex> worldIndexList = new HashMap<String, WorldIndex>();
		Map<String, Futures> futuresList = new HashMap<String, Futures>();
		Map<String, WorldFutures> worldFuturesList = new HashMap<String, WorldFutures>();
		
		Map<String, Fx> fxList = new HashMap<String, Fx>();
		Map<String, Metal> metalList = new HashMap<String, Metal>();
		Oil oil = null;
		
		String serverTime = "";
		
		try
		{
			// Stock,Index
			NodeList indexNodeList = iDocument.getElementsByTagName("STOCKLIST");
			try
			{
				NodeList indexNodes = indexNodeList.item(0).getChildNodes();
				for (int i = 1; i < indexNodes.getLength(); i++)
				{
					Element bElement = (Element) indexNodes.item(i);
					NodeList childNodes = bElement.getChildNodes();
					
					// Index
					if(bElement.getAttributes().getLength() > 0/* && "INDEX".equals(bElement.getAttributes().item(0).getFirstChild().getNodeValue())*/)
					{
	//					Node attrNode = bElement.getAttributes().item(0);
	//					System.out.println(attrNode.getNodeName()+" , "+attrNode.getFirstChild().getNodeValue());
						// Object
						Index index = new Index();
						for (int j = 0; j < childNodes.getLength(); j++)
						{
							try
							{
								if (childNodes.item(j).getNodeType() == Node.ELEMENT_NODE)
								{
									String name = childNodes.item(j).getNodeName();
									for(int k = 0; k < Index.FIELD_ITEMS_MONITOR.length; k++)
									{
										try
										{
											if (Index.FIELD_ITEMS_MONITOR[k].equals(name))
											{
												index.SetValueByFIELDS_MONITOR(k, childNodes.item(j).getFirstChild().getNodeValue());
												TDStockLog.d("Monitor", "Index=>"+name+":"+childNodes.item(j).getFirstChild().getNodeValue());
												break;
											}
										}
										catch(Exception e)
										{
										}
									}
								}
							}
							catch(Exception e)
							{
								e.printStackTrace();
							}
						}
						indexList.put(index.getName(), index);
					}
					else  // Stock
					{
						Stock stock = new Stock();
						for (int j = 0; j < childNodes.getLength(); j++)
						{
							try
							{
								if (childNodes.item(j).getNodeType() == Node.ELEMENT_NODE)
								{
									String name = childNodes.item(j).getNodeName();
									for(int k = 0; k < Stock.FIELD_ITEMS_MONITOR.length; k++)
									{
										try
										{
											if (Stock.FIELD_ITEMS_MONITOR[k].equals(name))
											{
												stock.SetValueByFIELDS_MONITOR(k, childNodes.item(j).getFirstChild().getNodeValue());
												TDStockLog.d("Monitor", "Stock=>"+name+":"+childNodes.item(j).getFirstChild().getNodeValue());
												break;
											}
										}
										catch(Exception e)
										{
										}
									}
								}
							}
							catch(Exception e)
							{
								e.printStackTrace();
							}
						}
						stockList.put(stock.getStock_code(), stock);
					}
				}
			}
			catch(Exception e)
			{
				e.printStackTrace();
			}
			
			// Futures
			NodeList futureNodeList = iDocument.getElementsByTagName("Future");
			try
			{
				NodeList futureIndexNodes = futureNodeList.item(0).getChildNodes();
				for (int i = 0; i < futureIndexNodes.getLength(); i++)
				{
					try
					{
						Element bElement = (Element) futureIndexNodes.item(i);
						
						if(bElement == null)
							continue;
						
						NodeList childNodes = bElement.getChildNodes();
						
						// Object
						Futures futures = new Futures();
						WorldFutures worldFutures = new WorldFutures();
						String value = null;
						for (int j = 0; j < childNodes.getLength(); j++)
						{
							try
							{
								if (childNodes.item(j).getNodeType() == Node.ELEMENT_NODE)
								{
									String name = childNodes.item(j).getNodeName();
									if(Futures.FIELD_ITEMS_MONITOR[0].equals(name) || WorldFutures.FIELD_ITEMS_MONITOR[0].equals(name))
									{
										Node n = childNodes.item(j).getFirstChild();
										if(n==null)
											continue;
										else
											value = n.getNodeValue();
									}
									
									if(Futures.TypeName_Str.contains(value))
									{
										for(int k = 0; k < Futures.FIELD_ITEMS_MONITOR.length; k++)
										{
											if (Futures.FIELD_ITEMS_MONITOR[k].equals(name))
											{
												futures.SetValueByFIELDS_MONITOR(k, childNodes.item(j).getFirstChild().getNodeValue());
												TDStockLog.d("Monitor", "Futures=>"+name+":"+childNodes.item(j).getFirstChild().getNodeValue());
												break;
											}
										}
									}
									else
									{
										for(int k = 0; k < WorldFutures.FIELD_ITEMS_MONITOR.length; k++)
										{
											if (WorldFutures.FIELD_ITEMS_MONITOR[k].equals(name))
											{
												worldFutures.SetValueByFIELDS_MONITOR(k, childNodes.item(j).getFirstChild().getNodeValue());
												TDStockLog.d("Monitor", "WorldFutures=>"+name+":"+childNodes.item(j).getFirstChild().getNodeValue());
												break;
											}
										}
									}
								}
							}
							catch(Exception e)
							{
								e.printStackTrace();
							}
						}
						if(futures.getName() != null)
						{
							futuresList.put(futures.getName(), futures);
						}
						else
						{
							worldFuturesList.put(worldFutures.getName(), worldFutures);
						}
					}
					catch(Exception e)
					{
						e.printStackTrace();
					}
				}
			}
			catch(Exception e)
			{
				e.printStackTrace();
			}
			
			// WorldIndex
			NodeList worldIndexNodeList = iDocument.getElementsByTagName("Index");
			try
			{
				NodeList worldIndexNodes = worldIndexNodeList.item(0).getChildNodes();
				for(int i = 0; i < worldIndexNodes.getLength(); i++)
				{
					Element bElement = (Element) worldIndexNodes.item(i);
					
					if(bElement == null)
						continue;
					
					NodeList childNodes = bElement.getChildNodes();
					// Object
					WorldIndex worldIndex = new WorldIndex();
					for (int j = 0; j < childNodes.getLength(); j++)
					{
						try
						{
							if (childNodes.item(j).getNodeType() == Node.ELEMENT_NODE)
							{
								String name = childNodes.item(j).getNodeName();
								for(int k = 0; k < WorldIndex.FIELD_ITEMS_MONITOR.length; k++)
								{
									if (WorldIndex.FIELD_ITEMS_MONITOR[k].equals(name))
									{
										worldIndex.SetValueByFIELDS_MONITOR(k, childNodes.item(j).getFirstChild().getNodeValue());
										TDStockLog.d("Monitor", "WorldIndex=>"+name+":"+childNodes.item(j).getFirstChild().getNodeValue());
										break;
									}
								}
							}
						}
						catch(Exception e)
						{
							e.printStackTrace();
						}
					}
					if(worldIndex.getName() != null)
						worldIndexList.put(worldIndex.getName(), worldIndex);
				}
			}
			catch(Exception e)
			{
				e.printStackTrace();
			}
			
			// FX
			NodeList fxNodeList = iDocument.getElementsByTagName("FXLIST");
			try
			{
				NodeList fxNodes = fxNodeList.item(0).getChildNodes();
				for(int i = 0; i < fxNodes.getLength(); i++)
				{
					Element bElement = (Element) fxNodes.item(i);
					
					if(bElement == null)
						continue;
					
					NodeList childNodes = bElement.getChildNodes();
					// Object
					Fx fx = new Fx();
					for (int j = 0; j < childNodes.getLength(); j++)
					{
						try
						{
							if (childNodes.item(j).getNodeType() == Node.ELEMENT_NODE)
							{
								String name = childNodes.item(j).getNodeName();
								for(int k = 0; k < Fx.FIELD_ITEMS_MONITOR.length; k++)
								{
									if (Fx.FIELD_ITEMS_MONITOR[k].equals(name))
									{
										fx.SetValueByFIELDS_MONITOR(k, childNodes.item(j).getFirstChild().getNodeValue());
										TDStockLog.d("Monitor", "Fx=>"+name+":"+childNodes.item(j).getFirstChild().getNodeValue());
										break;
									}
								}
							}
						}
						catch(Exception e)
						{
							e.printStackTrace();
						}
					}
					fxList.put(fx.getName(), fx);
				}
			}
			catch(Exception e)
			{
//				e.printStackTrace();
				TDStockLog.d(LOG_TAG, "BMP Monitor=>Fx: " + e.toString());
			}
			
			// Metal
			NodeList metalNodeList = iDocument.getElementsByTagName("METALLIST");
			try
			{
				NodeList metalNodes = metalNodeList.item(0).getChildNodes();
				for(int i = 0; i < metalNodes.getLength(); i++)
				{
					Element bElement = (Element) metalNodes.item(i);
					
					if(bElement == null)
						continue;
					
					NodeList childNodes = bElement.getChildNodes();
					// Object
					Metal metal = new Metal();
					for (int j = 0; j < childNodes.getLength(); j++)
					{
						try
						{
							if (childNodes.item(j).getNodeType() == Node.ELEMENT_NODE)
							{
								String name = childNodes.item(j).getNodeName();
								for(int k = 0; k < Metal.FIELD_ITEMS_MONITOR.length; k++)
								{
									if (Metal.FIELD_ITEMS_MONITOR[k].equals(name))
									{
										metal.SetValueByFIELDS_MONITOR(k, childNodes.item(j).getFirstChild().getNodeValue());
										TDStockLog.d("Monitor", "Metal=>"+name+":"+childNodes.item(j).getFirstChild().getNodeValue());
										break;
									}
								}
							}
						}
						catch(Exception e)
						{
							e.printStackTrace();
						}
					}
					metalList.put(metal.getName(), metal);
				}
			}
			catch(Exception e)
			{
//				e.printStackTrace();
				TDStockLog.d(LOG_TAG, "BMP Monitor=>Metal: " + e.toString());
			}
			
			// Oil
			NodeList oilNodeList = iDocument.getElementsByTagName("OILLIST");
			try
			{
				NodeList oilNodes = oilNodeList.item(0).getChildNodes();
				Element bElement = (Element) oilNodes.item(0);
				NodeList childNodes = bElement.getChildNodes();
				// Object
				oil = new Oil();
				for (int j = 0; j < childNodes.getLength(); j++)
				{
					try
					{
						if (childNodes.item(j).getNodeType() == Node.ELEMENT_NODE)
						{
							String name = childNodes.item(j).getNodeName();
							for(int k = 0; k < Oil.FIELD_ITEMS_MONITOR.length; k++)
							{
								if (Oil.FIELD_ITEMS_MONITOR[k].equals(name))
								{
									oil.SetValueByFIELDS_MONITOR(k, childNodes.item(j).getFirstChild().getNodeValue());
									TDStockLog.d("Monitor", "Oil=>"+name+":"+childNodes.item(j).getFirstChild().getNodeValue());
									break;
								}
							}
						}
					}
					catch(Exception e)
					{
						e.printStackTrace();
					}
				}
			}
			catch(Exception e)
			{
//				e.printStackTrace();
				TDStockLog.d(LOG_TAG, "BMP Monitor=>Metal: " + e.toString());
			}
			
			// Server Time
			NodeList timeNodes = iDocument.getElementsByTagName("Time");
			try
			{
				if(timeNodes.item(0).getNodeType() == Node.ELEMENT_NODE)
				{
					try
					{
						serverTime = timeNodes.item(0).getFirstChild().getNodeValue();
						TDStockLog.d("Monitor", "ServerTime=>"+serverTime);
					}
					catch(Exception e)
					{
						e.printStackTrace();
					}
				}
			}
			catch(Exception e)
			{
				e.printStackTrace();
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		return new Object[] { stockList, indexList, worldIndexList, futuresList, worldFuturesList, fxList, metalList, oil, serverTime };
	}
	
	private void TransactionByFieldListInfoDecode(Document iDoc, List<String[]> iInfoList, List<String[]> iAttrList)
	{
		if(entityRootName == null || fieldNames == null || fieldNames.length <= 0) return;
		
		NodeList focusList;
		Node focusNode;
		int index, count;

		String[] iEntityName = entityRootName.split(",");
		for(String iERName : iEntityName) // Foreach all Entity
		{
			focusList = iDoc.getElementsByTagName(iERName);
	
			count = focusList.getLength();
			
			long startTime = System.currentTimeMillis();
			
			if(debugMode)
			{
				String tmp = "XML-FieldName=> ";
				for(String t:fieldNames)
					tmp+= t + ",";
				TDStockLog.i(LOG_TAG, tmp);
			}
				
			for (index = 0; index < count; index++) // Entity list
			{
				Element element = (Element) focusList.item(index);
				NodeList childNodes = element.getChildNodes();
	
				int iIndex = 0;
				String[] tmpValues = null;;
				String[] attrValues = null;
				
				TDStockLog.d(LOG_TAG, "FieldSize:" + childNodes.getLength());
				
				for (int j = 0; j < childNodes.getLength(); j++) // Foreach all field
				{
					if (childNodes.item(j).getNodeType() == Node.ELEMENT_NODE)
					{
						if(tmpValues == null)
							tmpValues = new String[childNodes.getLength()];
						
						if(fieldAttributes != null && attrValues == null)
							attrValues= new String[childNodes.getLength()];
						
						focusNode = childNodes.item(j);
						if(focusNode == null)
							continue;
						
						try
						{
							if (fieldNames[0].equals(focusNode.getNodeName()))
							{
								tmpValues[iIndex] = focusNode.getFirstChild().getNodeValue();
								
								if(debugMode)
									TDStockLog.i(LOG_TAG, "XML-FieldValue=> " + tmpValues[iIndex]);
								
								if(fieldAttributes != null)
								{
									TDStockLog.d(LOG_TAG, "Attr.size:" + focusNode.getAttributes().getLength() + ","+fieldAttributes[0]);
									
									Attr attr = (Attr)focusNode.getAttributes().getNamedItem(fieldAttributes[0]);
									attrValues[iIndex] = attr.getValue();
									
									TDStockLog.d(LOG_TAG, "AttrValue: " + attrValues[j]);
								}
								iIndex++;
							}
						}
						catch (Exception e)
						{
							e.printStackTrace();
						}
					}
				}
				
				if(tmpValues != null)
				{
					String[] tmps = new String[iIndex];
					for(int i = 0; i < iIndex; i++)
					{
						tmps[i] = tmpValues[i];
					}
					iInfoList.add(tmps);
				}
				if(fieldAttributes != null && attrValues != null)
				{
					String[] tmps = new String[iIndex];
					for(int i = 0; i < iIndex; i++)
					{
						tmps[i] = attrValues[i];
					}
					iAttrList.add(tmps);
				}
			}
//			for(String[] tmp : iInfoList)
//			{
//				for(String tStr:tmp)
//				{
//					TDStockLog.d(LOG_TAG, "Value="+tStr);
//				}
//			}
			TDStockLog.d(LOG_TAG, "Doc UseTime:"+(System.currentTimeMillis() - startTime));
		}
	}
	
	/** Decode the inner portion of the group from quick pick response **/
	private void TransactionInfoDecode(Document iDoc, List<String[]> iInfoList, List<String[]> iAttrList)
	{
		if(entityRootName == null || fieldNames == null || fieldNames.length <= 0) return;
		
		NodeList focusList;
		Node focusNode;
		int index, count;

		String[] iEntityName = entityRootName.split(",");
		for(String iERName : iEntityName) // Foreach all Entity
		{
			focusList = iDoc.getElementsByTagName(iERName);
	
			count = focusList.getLength();
			
			long startTime = System.currentTimeMillis();
			
			if(debugMode)
			{
				String tmp = "XML-FieldName=> ";
				for(String t:fieldNames)
					tmp+= t + ",";
				TDStockLog.i(LOG_TAG, tmp);
			}
				
			for (index = 0; index < count; index++) // Entity list
			{
				Element element = (Element) focusList.item(index);
				NodeList childNodes = element.getChildNodes();
	
				String[] tmpValues = new String[fieldNames.length];
				String[] attrValues = null;
				
				if(fieldAttributes != null)
					attrValues= new String[fieldAttributes.length];
				
				for (int j = 0; j < childNodes.getLength(); j++) // Foreach all field
				{
					if (childNodes.item(j).getNodeType() == Node.ELEMENT_NODE)
					{
						focusNode = childNodes.item(j);
						if(focusNode == null)
							continue;
						for (int k = 0; k < fieldNames.length; k++)
						{
							try
							{
								if (fieldNames[k].equals(focusNode.getNodeName()))
								{
									tmpValues[k] = focusNode.getFirstChild() !=null ? focusNode.getFirstChild().getNodeValue() : null;
									if(debugMode)
										TDStockLog.i(LOG_TAG, "XML-FieldValue=> " + tmpValues[k]);
									
									if(fieldAttributes != null)
									{
										TDStockLog.d(LOG_TAG, "Attr.size:" + focusNode.getAttributes().getLength() + ","+fieldAttributes[k]);
										
										Attr attr = (Attr)focusNode.getAttributes().getNamedItem(fieldAttributes[k]);
										attrValues[k] = attr.getValue();
										
										TDStockLog.d(LOG_TAG, "AttrValue: " + attrValues[k]);
									}
									break;
								}
							}
							catch (Exception e)
							{
								e.printStackTrace();
							}
						}
					}
				}
				iInfoList.add(tmpValues);
			}
//			for(String[] tmp : iInfoList)
//			{
//				String tStr = "";
//				for(String s:tmp)
//				{
//					tStr += s+",";
//				}
//				TDStockLog.d(LOG_TAG, "Value="+tStr);
//			}
			TDStockLog.d(LOG_TAG, "Doc UseTime:"+(System.currentTimeMillis() - startTime));
		}
	}
	
	// For Document
	protected String[] headerFieldNames, fieldNames;
	protected String rootName, entityRootName;
	protected boolean fieldValueList;
	
	public void SetFieldValue(boolean isFieldValue)
	{
		fieldValueList = isFieldValue;
	}
	
	public void SetDocumentFieldInformation(String rName, String[] iHeaderFields, String rEntityName, String[] fields/*, String iStatus, String eMsg*/)
	{
		rootName = rName;
		entityRootName = rEntityName;
		fieldNames = fields;
		headerFieldNames = iHeaderFields;
	}
	
	protected String[] fieldAttributes;
	public void SetFieldAttributes(String[] iFAttributes)
	{
		fieldAttributes = iFAttributes;
	}
}
